package com.jiantong.web.open.app.work;

import com.google.common.collect.Maps;
import com.jiantong.user.service.BreedFactoryReadService;
import com.jiantong.web.core.enums.ExceptionCode;
import com.jiantong.work.dto.ImmunizationRecordDto;
import com.jiantong.work.model.ImmunizationRecord;
import com.jiantong.work.model.ImmunizationSubRecord;
import com.jiantong.work.service.ImmunizationRecordReadService;
import com.jiantong.work.service.ImmunizationRecordWriteService;
import com.jiantong.work.service.ImmunizationSubRecordReadService;
import io.terminus.boot.rpc.common.annotation.RpcConsumer;
import io.terminus.common.model.Paging;
import io.terminus.common.model.Response;
import io.terminus.pampas.openplatform.annotations.OpenBean;
import io.terminus.pampas.openplatform.annotations.OpenMethod;
import io.terminus.pampas.openplatform.exceptions.OPClientException;
import io.terminus.pampas.openplatform.exceptions.OPServerException;
import lombok.extern.slf4j.Slf4j;
import org.assertj.core.util.Strings;
import org.joda.time.DateTime;
import org.springframework.web.bind.annotation.RequestMethod;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 *免疫记录
 * Created by maowenjie on 2017/3/30.
 *
 */
@Slf4j
@OpenBean
public class ImmunizationRecordApis {
    @RpcConsumer
    private ImmunizationRecordReadService immunizationRecordReadService;
    @RpcConsumer
    private ImmunizationRecordWriteService immunizationRecordWriteService;
    @RpcConsumer
    private BreedFactoryReadService breedFactoryReadService;
    @RpcConsumer
    private ImmunizationSubRecordReadService immunizationSubRecordReadService;

    @OpenMethod(
            key = "find.immunization.record.by.id",
            paramNames = {"id"},
            httpMethods = RequestMethod.GET
    )
    public ImmunizationRecordDto findById(Long id){
        if(id == null){
            log.error("id should be not null");
            throw new OPClientException(ExceptionCode.ID_NOT_EXIST.value(),"id should be not null");
        }
        Response<ImmunizationRecord> resp = immunizationRecordReadService.findById(id);
        if (!resp.isSuccess()){
            log.error("failed to find immunization record by id = {}, cause : {}", id, resp.getError());
            throw new OPServerException(ExceptionCode.DATA_NOT_FOUND.value(),
                    resp.getError());
        }

        Response<List<ImmunizationSubRecord>> listResponse = immunizationSubRecordReadService.selectList(id);
        if(!listResponse.isSuccess()){
            log.error("failed to find immunization sub record case = {}",listResponse.getError());
            throw new OPServerException(ExceptionCode.DATA_NOT_FOUND.value(),listResponse.getError());
        }
        List<Map<String , Object>> vaccines = buildVaccineMapList(listResponse.getResult());
        ImmunizationRecordDto immunizationRecordDto = new ImmunizationRecordDto();
        immunizationRecordDto.setImmunizationRecord(resp.getResult());
        immunizationRecordDto.setVaccines(vaccines);
        return immunizationRecordDto;
    }

    @OpenMethod(
            key = "paging.immunization.record",
            paramNames = {"pageNo", "pageSize","status","breedFactoryId"},
            httpMethods = RequestMethod.GET
    )
    public Paging<ImmunizationRecordDto> pagingImmunizationRecord(Integer pageNo, Integer pageSize,
                                                               Integer status, Long breedFactoryId){
        if(breedFactoryId == null){
            log.error("breedFactoryId should be not null");
            throw new OPClientException(ExceptionCode.ID_NOT_EXIST.value(),
                    "breedFactoryId should be not null");
        }
        Response <Paging<ImmunizationRecord>> resp =
                immunizationRecordReadService.pagingImmunizationRecord(pageNo,pageSize,status,breedFactoryId);
        if(!resp.isSuccess()){
            log.error("failed to paging immunization record by id = {}, cause : {}", status, resp.getError());
            throw new OPServerException(ExceptionCode.DATA_NOT_FOUND.value(),
                    resp.getError());
        }
        List<ImmunizationRecordDto> immunizationRecordDtos = new ArrayList<>();
        ImmunizationRecordDto immunizationRecordDto = null;
        List<ImmunizationRecord> immunizationRecords = resp.getResult().getData();
        for(ImmunizationRecord immunizationRecord : immunizationRecords){
            Long vaccineId = immunizationRecord.getId();
            Response<List<ImmunizationSubRecord>> response = immunizationSubRecordReadService.selectList(vaccineId);
            if(!response.isSuccess()){
                log.error("failed to find immunization sub record case = {}",response.getError());
                throw new OPServerException(ExceptionCode.DATA_NOT_FOUND.value(),response.getError());
            }
            immunizationRecordDto = new ImmunizationRecordDto();
            immunizationRecordDto.setVaccines(buildVaccineMapList(response.getResult()));
            immunizationRecordDto.setImmunizationRecord(immunizationRecord);
            immunizationRecordDtos.add(immunizationRecordDto);
        }

        Paging<ImmunizationRecordDto> paging = new Paging<>();
        paging.setTotal(resp.getResult().getTotal());
        paging.setData(immunizationRecordDtos);
        return paging;
    }

    @OpenMethod(
            key = "create.immunization.report",
            paramNames = {"immunizationRecordDto","toStatus"},
            httpMethods = RequestMethod.POST
    )
    public Map<String,Object> create(ImmunizationRecordDto immunizationRecordDto, Integer toStatus){

        Response<Map<String,Object>>response = immunizationRecordWriteService.create(immunizationRecordDto,toStatus);
        if(!response.isSuccess()){
            log.error("failed to create immunization report  by immunizationRecord = {}, cause : {}", immunizationRecordDto,toStatus, response.getError());
            throw new OPServerException(ExceptionCode.DATA_WRITE_FAIL.value(),
                    response.getError());
        }
        return response.getResult();
    }
    @OpenMethod(
            key = "update.immunization.record",
            paramNames = {"immunizationRecordDto","toStatus"},
            httpMethods = RequestMethod.PUT
    )
    public Map<String,Object> update(ImmunizationRecordDto immunizationRecordDto,Integer toStatus){
        ImmunizationRecord immunizationRecord = immunizationRecordDto.getImmunizationRecord();
        if(immunizationRecord.getId() == null){
            log.error("id should be not null error = {}, cause : {}", immunizationRecord,immunizationRecord.getId());
            throw new OPClientException(ExceptionCode.ID_NOT_EXIST.value(),
                    "id should be not null");
        }
        Response<Map<String , Object>> statusResponse = immunizationRecordReadService.findStatusById(immunizationRecord.getId());
        if(statusResponse.isSuccess() && !statusResponse.getResult().get("status").equals(immunizationRecord.getStatus())){
            log.error("immunizationRecord is already submitted error = {}, cause : {}", immunizationRecord.getStatus(),statusResponse.getResult().get("status"));
            throw new OPClientException(ExceptionCode.DOCUMENT_REPEAT_SUBMIT.value(),
                    "this.report.is.already.submitted");
        }
        Response<Map<String,Object>> response = immunizationRecordWriteService.update(immunizationRecordDto,toStatus);
        if(!response.isSuccess()){
            log.error("failed to update immunization record = {}, cause : {}", immunizationRecordDto,toStatus, response.getError());
            throw new OPServerException(ExceptionCode.DATA_UPDATE_FAIL.value(),
                    response.getError());
        }
        return response.getResult();
    }


    /**
     * 政府端时间查询
     *
     * @return status =1
     */
    @OpenMethod(
            key = "paging.status.immunization.record",
            paramNames = {"pageNo", "pageSize", "breedFactoryId","breedType", "fromDate", "toDate"},
            httpMethods = RequestMethod.GET
    )
    public Paging<ImmunizationRecordDto> pagingImmunizationRecord(Integer pageNo,
                                                                  Integer pageSize,
                                                                  Long breedFactoryId,
                                                                  Integer breedType,
                                                                  String fromDate,
                                                                  String toDate) {

        Date start = null;
        if (!Strings.isNullOrEmpty(fromDate)) {
            start = DateTime.parse(fromDate).toDate();
        }

        Date end = null;
        if (!Strings.isNullOrEmpty(toDate)) {
            end = DateTime.parse(toDate).toDate();
        }
        Response<Paging<ImmunizationRecord>> resp =
                immunizationRecordReadService.pagingImmunizationRecordGqv(pageNo, pageSize, breedFactoryId,breedType, start, end);
        if (!resp.isSuccess()) {
            log.error("failed to paging immunizationRecord center{}, cause : {}", resp.getError());
            throw new OPServerException(ExceptionCode.DATA_NOT_FOUND.value(),
                    resp.getError());
        }
        List<ImmunizationRecordDto> immunizationRecordDtos = new ArrayList<>();
        ImmunizationRecordDto immunizationRecordDto = null;
        List<ImmunizationRecord> immunizationRecords = resp.getResult().getData();
        for(ImmunizationRecord immunizationRecord : immunizationRecords){
            Long vaccineId = immunizationRecord.getId();
            Response<List<ImmunizationSubRecord>> response = immunizationSubRecordReadService.selectList(vaccineId);
            if(!response.isSuccess()){
                log.error("failed to find immunization sub record case = {}",response.getError());
                throw new OPServerException(ExceptionCode.DATA_NOT_FOUND.value(),response.getError());
            }
            immunizationRecordDto = new ImmunizationRecordDto();
            immunizationRecordDto.setVaccines(buildVaccineMapList(response.getResult()));
            immunizationRecordDto.setImmunizationRecord(immunizationRecord);
            immunizationRecordDtos.add(immunizationRecordDto);
        }

        Paging<ImmunizationRecordDto> paging = new Paging<>();
        paging.setTotal(resp.getResult().getTotal());
        paging.setData(immunizationRecordDtos);
        return paging;
    }


    private List<Map<String , Object>> buildVaccineMapList(List<ImmunizationSubRecord> list){
        List<Map<String , Object>> vaccines = new ArrayList<>();
        Map<String , Object> vaccine = null;
        for(ImmunizationSubRecord immunizationSubRecord : list){
            vaccine = Maps.newHashMap();
            vaccine.put("id",immunizationSubRecord.getId());
            vaccine.put("vaccineId",immunizationSubRecord.getVaccineId());
            vaccine.put("stableId",immunizationSubRecord.getStableId());
            vaccine.put("stableNumber",immunizationSubRecord.getStableNumber());
            vaccine.put("area",immunizationSubRecord.getArea());
            vaccine.put("date",immunizationSubRecord.getDate());
            vaccine.put("type",immunizationSubRecord.getType());
            vaccine.put("otherType",immunizationSubRecord.getOtherType());
            vaccine.put("vaccineCode",immunizationSubRecord.getVaccineCode());
            vaccine.put("vaccineName",immunizationSubRecord.getVaccineName());
            vaccine.put("days",immunizationSubRecord.getDays());
            vaccine.put("times",immunizationSubRecord.getTimes());
            vaccine.put("quantity",immunizationSubRecord.getQuantity());
            vaccine.put("drugQuantity",immunizationSubRecord.getDrugQuantity());
            vaccine.put("operatorName",immunizationSubRecord.getOperatorName());
            vaccine.put("method",immunizationSubRecord.getMethod());
            vaccine.put("drugUnit",immunizationSubRecord.getDrugUnit());
            vaccine.put("manufacturer",immunizationSubRecord.getManufacturer());
            vaccine.put("batch",immunizationSubRecord.getBatch());
            vaccines.add(vaccine);
        }
        return vaccines;
    }
}
